﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NLog;

namespace WebCrawlerHelper.Controllers
{
    public class HttpController
    {
        private static readonly Logger NLogger = LogManager.GetCurrentClassLogger();

        private static readonly HttpClient HttpClient = new HttpClient();

        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true;
        }

        public static async Task<string> GetAsync(string uri, Encoding encode = null)
        {
            //验证服务器证书回调自动验证
            ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;

            //var httpClient = new HttpClient();

            HttpResponseMessage response = await HttpClient.GetAsync(uri);

            //response.EnsureSuccessStatusCode();

            Stream myResponseStream = await response.Content.ReadAsStreamAsync();
            if (encode == null)
            {
                encode = Encoding.Default;
            }
            StreamReader myStreamReader = new StreamReader(myResponseStream, encode);
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();
            return retString;
        }

        /// <summary>
        /// 通过代理Get
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="proxyIp"></param>
        /// <param name="proxyPort"></param>
        /// <returns></returns>
        public static async Task<string> GetAsyncByProxy(string uri, string proxyIp, int proxyPort, Encoding encode = null)
        {
            var proxyUrl = $"http://{proxyIp}:{proxyPort}";
            var httpClientHandler = new HttpClientHandler
            {
                Proxy = new WebProxy(proxyUrl, false),
                UseProxy = true
            };

            using (var hc = new HttpClient(httpClientHandler) {Timeout = TimeSpan.FromSeconds(5)})
            {
                //验证服务器证书回调自动验证
                ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;

                HttpResponseMessage response = await hc.GetAsync(uri);

                Stream myResponseStream = await response.Content.ReadAsStreamAsync();
                if (encode == null)
                {
                    encode = Encoding.Default;
                }
                StreamReader myStreamReader = new StreamReader(myResponseStream, encode);
                string retString = myStreamReader.ReadToEnd();
                myStreamReader.Close();
                myResponseStream.Close();
                return retString;

                //var result = await response.Content.ReadAsStringAsync();
                //return result;
            }

        }

        public static async Task<string> GetOriginalRequestUri(string uri)
        {
            //验证服务器证书回调自动验证
            ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;

            var httpClient = new HttpClient
            {
                Timeout = TimeSpan.FromSeconds(5)
            };

            HttpResponseMessage response = await httpClient.GetAsync(uri);

            var result = response.RequestMessage.RequestUri.OriginalString;

            httpClient.Dispose();

            return result;
        }

        public static async Task<string> PostAsync<T>(string url, string api, T value)
        {
            //验证服务器证书回调自动验证
            ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;

            HttpClient httpClient = new HttpClient(new HttpClientHandler());

            MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter { UseDataContractJsonSerializer = true };

            var response = await httpClient.PostAsync(url + api, value, jsonFormatter);

            var res = false;
            try
            {
                response.EnsureSuccessStatusCode();
            }
            catch (Exception e)
            {
                res = true;
            }
            if (res)
            {
                response = await httpClient.PostAsync(url + api, value, jsonFormatter);
            }
            string result = await response.Content.ReadAsStringAsync();

            return result;
        }


        /// <summary>
        /// POST方法， application/x-www-form-urlencoded
        /// </summary>
        /// <param name="url"></param>
        /// <param name="listValue"></param>
        /// <returns></returns>
        public static async Task<string> PostAsync(string url, List<KeyValuePair<string, string>> listValue)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(url);
                var content = new FormUrlEncodedContent(listValue);
                var result = await client.PostAsync(url, content);
                string resultContent = await result.Content.ReadAsStringAsync();
                return resultContent;
            }
        }





        public static string PostData(string url, string postData, Encoding encode = null)
        {
            ASCIIEncoding encoding = new ASCIIEncoding();
            byte[] data = encoding.GetBytes(postData);
            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);

            myRequest.Method = "POST";
            myRequest.ContentType = "application/x-www-form-urlencoded";
            myRequest.ContentLength = data.Length;
            Stream newStream = myRequest.GetRequestStream();

            newStream.Write(data, 0, data.Length);
            newStream.Close();

            try
            {
                var response = myRequest.GetResponse();
                HttpWebResponse myResponse = (HttpWebResponse)response;
                StreamReader reader = null;
                if (encode == null)
                {
                    reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
                }
                else
                {
                    reader = new StreamReader(myResponse.GetResponseStream(), encode);
                }
                string content = reader.ReadToEnd();
                reader.Close();
                return content;
            }
            catch (Exception ex)
            {
                var statusCode = ((HttpWebResponse) ((WebException) ex).Response).StatusCode;
                NLogger.Error($"{ex.Message}|{statusCode}|{url}|{postData}");
                Thread.Sleep(1000);
                return PostData(url, postData, encode);
            }
        }

        public static string PostDataByProxy(string url, string postData, string proxyIp, int proxyPort, Encoding encode = null)
        {
            var proxyUrl = $"http://{proxyIp}:{proxyPort}";

            ASCIIEncoding encoding = new ASCIIEncoding();
            byte[] data = encoding.GetBytes(postData);
            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);

            myRequest.Proxy = new WebProxy(new Uri(proxyUrl), false);

            myRequest.Method = "POST";
            myRequest.ContentType = "application/x-www-form-urlencoded";
            myRequest.ContentLength = data.Length;
            Stream newStream = myRequest.GetRequestStream();

            newStream.Write(data, 0, data.Length);
            newStream.Close();
            
            try
            {


                using (HttpWebResponse response = myRequest.GetResponse() as HttpWebResponse)
                {
                    StreamReader StreamReader = new StreamReader(response.GetResponseStream());
                    string strReaderXML = StreamReader.ReadToEnd();
                    return strReaderXML;
                }


                //var response = myRequest.GetResponse();
                //HttpWebResponse myResponse = (HttpWebResponse)response;
                //StreamReader reader = null;
                //if (encode == null)
                //{
                //    reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
                //}
                //else
                //{
                //    reader = new StreamReader(myResponse.GetResponseStream(), encode);
                //}
                //string content = reader.ReadToEnd();
                //reader.Close();
                //return content;
            }
            catch (Exception ex)
            {
                if (((WebException) ex).Response != null)
                {
                    var statusCode = ((HttpWebResponse) ((WebException) ex).Response).StatusCode;
                    NLogger.Error($"{ex.Message}|{statusCode}|{url}|{postData}");
                    Thread.Sleep(1000);
                    return PostDataByProxy(url, postData, proxyIp, proxyPort, encode);
                }
                else
                {
                    NLogger.Error($"{ex.Message}|{url}|{postData}");
                    Thread.Sleep(1000);
                    return PostDataByProxy(url, postData, proxyIp, proxyPort, encode);
                }
            }
        }
    }
}
